using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;

using AspNetForums.Enumerations;
using AspNetForums.Components;
using AspNetForums.WebServices;

namespace AspNetForums.WebServices
{
	/// <summary>
	/// Summary description for ExpressSubmissions.
	/// </summary>
	public class ExpressSubmissions : System.Web.Services.WebService
	{
		public WsseUsernameTokenHeader UsernameToken;
		
		
		public ExpressSubmissions()
		{
			
		}

		#region Component Designer generated code
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			base.Dispose(disposing);		
		}
		#endregion

		#region Posts
		

		private PostError VerifyPost( SerializablePost post, SerializablePostAttachment[] attachments )
		{
			// Is the post in the set of Express Competition Forums?
			if( !IsValidForum( post.ForumID ) ) return PostError.InvalidForum;

			// Does the entry meet the entry criterion?
			if( post.Subject == "" ) return PostError.MissingSubject;
			if( post.Body == "" ) return PostError.MissingDescription;
			
			return VerifyAttachments(attachments);
		}

		private PostError VerifyAttachments(SerializablePostAttachment[] attachments)
		{
			if( attachments == null ) return PostError.None;

			bool found = false;
			foreach( SerializablePostAttachment attachment in attachments )
			{
				if( attachment.Type == LinkType.Zip )
				{
					if( attachment.Files.Length == 0 ) break;
					if( !VerifyProject(attachment) ) break;
					found = true;
				}
				else if( attachment.Type == LinkType.Photo )
				{
					// 500x500x32bit = 1,000,000 bytes uncompressed. NO IMAGES SHOULD EVEN APROACH THIS SIZE
					if( attachment.Files.Length == 0 || attachment.Files[0].Contents.Length > 1000000 )
						return PostError.InvalidProject;
				}
				else
				{
					return PostError.InvalidProject;
				}
			}
			if( !found ) return PostError.InvalidProject;

			return PostError.None;
		}

		private bool VerifyProject(SerializablePostAttachment attachment)
		{
			return true;
		}

		private bool IsValidForum(int forumID)
		{
			Forum forum = Forums.GetForum(forumID, true, true);
			return IsValidForum(forum);
		}

		private bool IsValidForum(Forum forum)
		{
#if DEBUG
			if( forum.ForumID == 1 ) return true;
#endif
			return forum.ForumGroupID.ToString() == Globals.GetConfigurationSetting("ExpressForumGroup") && forum.Name.StartsWith("Visual");
		}
		
		
		//[WebMethod]
		//[System.Web.Services.Protocols.SoapHeader("UsernameToken")]
		public SerializablePost AddPost( SerializablePost post )
		{
				return AddPost(post,true);
		}

		private SerializablePost AddPost( SerializablePost post, bool verify )
		{
			if( verify && !IsAuthenticated() )
				return null;
			
			if( verify ) post.Error = VerifyPost(post,null);
			
			if( post.Error == PostError.None )
			{
				Components.Post newPost = FormatPost( post );
				newPost = Posts.AddPost( newPost, UsernameToken.User );
				post = new SerializablePost(newPost);
			}
			
			return post;
		}
		
		
		[WebMethod(MessageName="AddPostWithAttachments")]
		[System.Web.Services.Protocols.SoapHeader("UsernameToken")]
		public SerializablePost AddPost( SerializablePost post, SerializablePostAttachment[] attachments )
		{
			if( !IsAuthenticated() )
				return null;

			InitializeAdminUser();

			post.Error = VerifyPost(post, attachments);

			if( post.Error == PostError.None )
			{
				post = this.AddPost( post, false );
			
				foreach( SerializablePostAttachment attachment in attachments )
				{
					AddPostAttachment( post, attachment );
				}
			}

			return post;
		}

		private void InitializeAdminUser()
		{
			bool admin = false;

			ArrayList roles = Roles.GetRoles(UsernameToken.User.UserID, true );
			foreach( Role role in roles )
			{
				if( role.Name == "Forum-Administrators" || role.Name == "Global-Administrators" )
				{
					admin = true;
				}
			}
			
			if( !admin )
				return;

			User user = null;
			try
			{
				user = Users.GetUser(-1, UsernameToken.Nonce, false, true);
			}
			catch( ForumException )
			{
				return;
			}

			if( user != null )
			{
				UsernameToken.User = user;
				UsernameToken.Username = user.Username;
			}
		}
		
		
		private Components.Post FormatPost(  SerializablePost post )
		{
			Components.Thread newPost = new AspNetForums.Components.Thread();
			newPost.Body = post.Body;
			newPost.Subject = post.Subject;
			newPost.ForumID = post.ForumID;
			
			newPost.IsSticky = false;
			newPost.StickyDate = DateTime.Now;
			newPost.PostType = Enumerations.PostType.HTML;
			newPost.Username = UsernameToken.Username;
			newPost.User = UsernameToken.User;
			newPost.IsApproved = true;
			return newPost;
		}

		private void AddPostAttachment( SerializablePost post, SerializablePostAttachment attachment )
		{
			Components.PostLink link = new AspNetForums.Components.PostLink();
			link.Type = attachment.Type;
			link.PostID = post.PostID;
			
			// BEWARE: CanSave is simply a check for savable formats, security MUST be checked elsewhere.
			if( attachment.CanSave )
			{
				link.Url = attachment.Save();
			}
			else if(attachment.Files.Length == 1 && attachment.Files[0].Contents == null)
			{
				link.Url = attachment.Files[0].RelativePath;
			}
			else
			{
				//TODO: throw InvalidArgumentException for SOAP
				return;
			}

			Posts.AddPostLink( link );
			return;
		
			
		}

		
		#endregion

		#region Forums
		
		[WebMethod]
		[System.Web.Services.Protocols.SoapHeader("UsernameToken")]
		public SerializableForum[] GetForums()
		{
			if( !IsAuthenticated() )
			{	
				this.UsernameToken = new WsseUsernameTokenHeader();
				this.UsernameToken.User = Users.GetAnonymousUser();
			}
			
			System.Collections.ArrayList forumsList = Forums.GetForums( this.UsernameToken.User.UserID, true, true );
			ArrayList forums = new ArrayList();
			
			if( forumsList != null )
			{
				foreach( Forum forum in forumsList )
				{
					if( IsValidForum(forum) )
					{
						forums.Add( new SerializableForum( (Components.Forum)forum ) );
					}
				}
			}	
			return (SerializableForum[])forums.ToArray(typeof(SerializableForum));
		}
		
		#endregion



		
		#region Authentication
		[WebMethod]
		[System.Web.Services.Protocols.SoapHeader("UsernameToken")]
		public Enumerations.LoginUserStatus GetAuthenticationStatus()
		{
			Enumerations.LoginUserStatus status = Enumerations.LoginUserStatus.UnknownError;
			status = UsernameToken.IsValid();
			return status;
		}

		private bool IsAuthenticated()
		{
			if( this.UsernameToken == null ) 
				return false;
			if( GetAuthenticationStatus() != Enumerations.LoginUserStatus.Success )
				return false;
			return true;
		}

		#endregion
	
	}

	
}
